// Copyright (c) 2008 Matthew Johnson
// Licensed under the MIT License (see license.txt)
package actionml.interaction {
	import actionml.Global;
	
	import actionml.animation.Tween;
	
	import flash.display.DisplayObject;
	import flash.events.MouseEvent;

	public class PopupInteractions {
		public static function initialize() {
			Global.initializeExtension(PopupInteractions, DisplayObject);
		}
		public static var instanceMethods:Object = {
			makePopup: function(options:Object=null) {
				if (this.isAlready("Popup")) return;
				this.visible = false;
				options ||= {};
				var o:DisplayObject = this;
				var closeButton:DisplayObject = this.getChildByName(options["closeButton"] || "closeButton");
				this.initialFocus = this.getChildByName(options["initialFocus"] || "") || closeButton;
				closeButton.makeButton();
				closeButton.addEventListener("click", function() {
					o.closePopup();
				});
				this.setPropertiesIfUndefined({
					showingX: ((this.root.width - this.width) / 2),
					hidingX: ((this.root.width - this.width) / 2),
					showingY: ((this.root.height - this.height) / 3),
					hidingY: ((this.root.height - this.height) / 3),
					showingAlpha: 1,
					hidingAlpha: 0
				});
				this.tweens ||= {};
				this.tweens["autoShow"] ||= new Tween({name: "autoShow", target:this, startState: "hiding", endState: "showing", alwaysPlayFromStart: true});
				this.tweens["autoHide"] ||= new Tween({name: "autoHide", target:this, startState: "showing", endState: "hiding", alwaysPlayFromStart: true});
				this["onShow"] ||= "playAutoShow";
				this["onHide"] ||= "playAutoHide";				
			},
			displayPopup: function() {
				this.returnFocus = Global.stage.focus;
				if (Global["handlingAccessibilityClick"]) {
					Global.stage.focus = this.initialFocus;	
				} else {
					Global.stage.focus = null;
				}
				this.tabEnabledObjects = [];
				this.mouseEnabledObjects = [];
				var o:DisplayObject = this;
				var dispatchedMouseOut:Boolean = false;
				this.root.walkTree(function(descendent:DisplayObject) {
					if (descendent != o) {
						var parent:DisplayObject = descendent.parent;
						while (parent != o.root) {
							if (parent == o) {
								return;
							}
							parent = parent.parent;
						}
						if ("mouseEnabled" in descendent && descendent["mouseEnabled"]) {
							o.mouseEnabledObjects.push(descendent);
							descendent["mouseEnabled"] = false;
							if (!dispatchedMouseOut && descendent["isThisOrChildTopObjectUnderPoint"](Global.stage.mouseX, Global.stage.mouseY, true, o.root["getCurtain"]())) {
								// switching visible off and on fools the mouse out handler into
								// handling the event even though the mouse is still over the object
								descendent.visible = false;
								descendent.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_OUT, true, true, Global.stage.mouseX, Global.stage.mouseY));
								descendent.visible = true;
								dispatchedMouseOut = true;
							}
						}
						if ("tabEnabled" in descendent && descendent["tabEnabled"]) {
							o.tabEnabledObjects.push(descendent);
							descendent["tabEnabled"] = false;
						}
					}
				}, false);
				this.root["getCurtain"]().moveToFront();
				this.root["getCurtain"]().playTween({startAlpha:0, alpha: "showingAlpha", alwaysPlayFromStart: true});
				this.moveToFront();
				this.doEvent("show");
			},
			closePopup: function() {
				this.root["getCurtain"]().playTween({startAlpha:"showingAlpha", alpha: 0, alwaysPlayFromStart: true});
				this.doEvent("hide");
				var o:DisplayObject = this;
				var returnFocus:DisplayObject = this.returnFocus;
				if (!Global["handlingAccessibilityClick"]) {
					returnFocus = null;
				}
				this.addEventListener("completeAllTweens", function() {
					for each (var te:DisplayObject in o.tabEnabledObjects) {
						te.tabEnabled = true;
					}
					for each (var me:DisplayObject in o.mouseEnabledObjects) {
						me.mouseEnabled = true;
						if (me["isThisOrChildTopObjectUnderPoint"](Global.stage.mouseX, Global.stage.mouseY, true, Global.document["getCurtain"]())) {
							me.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_OVER, true, true, Global.stage.mouseX, Global.stage.mouseY));
						}
					}
					Global.stage.focus = returnFocus;
					o.removeEventListener("completeAllTweens", arguments.callee);
				});
			}
		}
	}
}